package abel.wlmr.model.type;

import java.nio.charset.Charset;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrException;
import io.netty.buffer.ByteBuf;

/**
 * B.5.12.2.5.1 ERC1：数据初始化和版本变更记录
 * 事件记录的数据格式见表 B.185。
 * 表B.185 数据初始化和版本变更记录数据单元格式
 * 数据内容 数据格式 字节数
 * ERC=1 BIN 1
 * 长度 Le BIN 1
 * 初始化/版本变更时间：分时日月年 见附录 C.15 5
 * 事件标志 BS8 1
 * 变更前软件版本号 ASCII 4
 * 变更后软件版本号 ASCII 4
 * ——事件标志：
 * ● D0：置“1”：终端进行参数及数据区初始化，记录初始化时间；置“0”：无初始化发生；
 * ● D1：置“1”：终端版本变更，记录变更时间和变更前后版本号；置“0”：，版本未变更
 * 
 * @author Abel
 *
 */
public class Erc1Body extends ErcBaseBody {

    private static final short FIXED_LENGTH = 5 + 1 + 4 + 4;

    /**
     * 初始化/版本变更时间：分时日月年 见附录 C.15 5
     */
    private StdBcdNumber updateDate;

    /**
     * 事件标志 BS8 1
     * ——事件标志：
     * ● D0：置“1”：终端进行参数及数据区初始化，记录初始化时间；置“0”：无初始化发生；
     * ● D1：置“1”：终端版本变更，记录变更时间和变更前后版本号；置“0”：，版本未变更
     */
    private short eventFlag;

    /**
     * 变更前软件版本号 ASCII 4
     */
    private String versionBefore;

    /**
     * 变更后软件版本号 ASCII 4
     */
    private String versionAfter;

    public Erc1Body(short guessedLen) {
        super(guessedLen, (short) 1, FIXED_LENGTH);
    }

    public Erc1Body() {
        this((short) -1);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (updateDate == null || updateDate.length() != 5) {
            throw new IllegalArgumentException("update date in event should be 5 digits long");
        }
        if (versionBefore == null || versionBefore.length() != 4) {
            throw new IllegalArgumentException("version before should be 4 ascii long");
        }
        if (versionAfter == null || versionAfter.length() != 4) {
            throw new IllegalArgumentException("version after should be 4 ascii long");
        }

        // append erc & le.
        buf.writeByte(erc);
        buf.writeByte(le);

        buf.writeBytes(updateDate.toBytes());
        buf.writeByte(eventFlag);
        buf.writeBytes(versionBefore.getBytes());
        buf.writeBytes(versionAfter.getBytes());

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        buf.skipBytes(MIN_LENGTH);

        updateDate = new StdBcdNumber();
        updateDate.populateBytes(buf, 5);

        eventFlag = buf.readByte();

        versionBefore = buf.readCharSequence(4, Charset.defaultCharset()).toString();
        versionAfter = buf.readCharSequence(4, Charset.defaultCharset()).toString();

        return MIN_LENGTH + FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return MIN_LENGTH + FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{updateDate:%s, eventFlag:%s, versionBefore:%s, versionAfter:%s}", updateDate, eventFlag,
            versionBefore, versionAfter);
    }

    /**
     * 初始化/版本变更时间：分时日月年 见附录 C.15 5
     * 
     * @return the updateDate
     */
    public StdBcdNumber getUpdateDate() {
        return updateDate;
    }

    /**
     * 初始化/版本变更时间：分时日月年 见附录 C.15 5
     * 
     * @param updateDate
     *            the updateDate to set
     */
    public void setUpdateDate(StdBcdNumber updateDate) {
        if (updateDate == null || updateDate.length() != 5) {
            throw new IllegalArgumentException("update date in event should be 5 digits long");
        }

        // may throw IAE
        updateDate.toMeterC15Joda();

        this.updateDate = updateDate;
    }

    /**
     * 事件标志 BS8 1
     * ——事件标志：
     * ● D0：置“1”：终端进行参数及数据区初始化，记录初始化时间；置“0”：无初始化发生；
     * ● D1：置“1”：终端版本变更，记录变更时间和变更前后版本号；置“0”：，版本未变更
     * 
     * @return the eventFlag
     */
    public short getEventFlag() {
        return eventFlag;
    }

    /**
     * 事件标志 BS8 1
     * ——事件标志：
     * ● D0：置“1”：终端进行参数及数据区初始化，记录初始化时间；置“0”：无初始化发生；
     * ● D1：置“1”：终端版本变更，记录变更时间和变更前后版本号；置“0”：，版本未变更
     * 
     * @param eventFlag
     *            the eventFlag to set
     */
    public void setEventFlag(short eventFlag) {
        this.eventFlag = eventFlag;
    }

    /**
     * 变更前软件版本号 ASCII 4
     * 
     * @return the versionBefore
     */
    public String getVersionBefore() {
        return versionBefore;
    }

    /**
     * 变更前软件版本号 ASCII 4
     * 
     * @param versionBefore
     *            the versionBefore to set
     */
    public void setVersionBefore(String versionBefore) {
        if (versionBefore == null || versionBefore.length() != 4) {
            throw new IllegalArgumentException("version before should be 4 ascii long");
        }

        this.versionBefore = versionBefore;
    }

    /**
     * 变更后软件版本号 ASCII 4
     * 
     * @return the versionAfter
     */
    public String getVersionAfter() {
        return versionAfter;
    }

    /**
     * 变更后软件版本号 ASCII 4
     * 
     * @param versionAfter
     *            the versionAfter to set
     */
    public void setVersionAfter(String versionAfter) {
        if (versionAfter == null || versionAfter.length() != 4) {
            throw new IllegalArgumentException("version after should be 4 ascii long");
        }

        this.versionAfter = versionAfter;
    }
}
